package service

import (
	"context"
	"fmt"
	"strings"

	"database/sql"

	dbmodel "gitee.com/hp-huiw/family-expense-api/internal/db/model"
	"gitee.com/hp-huiw/family-expense-api/internal/dto"
	"gitee.com/hp-huiw/family-expense-api/internal/repository"
	"gitee.com/hp-huiw/my-go-core/config"
	"gitee.com/hp-huiw/my-go-core/date"
	"gitee.com/hp-huiw/my-go-core/util"
	"github.com/samber/lo"
)

type BankService interface {
	Initialize(ctx context.Context) error
	GetLogoUrl(shortName *string) *string
	QueryAllWithBasicInfo(ctx context.Context) ([]dto.BankResponse, error)
}

// NewBankService creates a new instance of BankService.
func NewBankService(db *sql.DB) BankService {
	return &bankService{
		db:             db,
		bankRepository: repository.NewBankRepository(db),
	}
}

// Initialize prepares the initial data for Bank.
func (s *bankService) Initialize(ctx context.Context) error {
	exists, err := s.bankRepository.Exists(ctx)

	if err != nil {
		return err
	}

	if !exists {
		models := []dbmodel.Bank{
			{
				ID:          util.GenerateUUIDWithoutDashes(),
				Name:        "建行",
				ShortName:   "CCB",
				DateCreated: date.GetCurrentDate(),
				LastUpdated: date.GetCurrentDate(),
			},
			{
				ID:          util.GenerateUUIDWithoutDashes(),
				Name:        "交行",
				ShortName:   "BCM",
				DateCreated: date.GetCurrentDate(),
				LastUpdated: date.GetCurrentDate(),
			},
			{
				ID:          util.GenerateUUIDWithoutDashes(),
				Name:        "招行",
				ShortName:   "CMB",
				DateCreated: date.GetCurrentDate(),
				LastUpdated: date.GetCurrentDate(),
			},
		}

		err = s.bankRepository.BatchInsert(ctx, models)
	}

	return err
}

// GetLogoUrl gets bank logo url based on its short name.
// return The full url of the bank logo.
func (*bankService) GetLogoUrl(shortName *string) *string {
	if shortName != nil && !util.IsEmptyString(*shortName) {
		// Gets current configuration.
		appConfig := config.ConfigLoader.GetAppConfig()

		return util.AnyPtr(fmt.Sprintf("%v%v/%v.png", appConfig.Resource.HttpBaseUrl, appConfig.Resource.BankLogoUrl, strings.ToLower(*shortName)))
	}

	return nil
}

// QueryAllWithBasicInfo queries all banks with basic info.
func (s *bankService) QueryAllWithBasicInfo(ctx context.Context) ([]dto.BankResponse, error) {
	query, err := s.bankRepository.QueryAllWithBasicInfo(ctx)

	if err != nil {
		return nil, err
	}

	result := lo.Map(query, func(item repository.Bank, _ int) dto.BankResponse {
		return dto.BankResponse{
			ID:        item.ID,
			Name:      item.Name,
			ShortName: item.ShortName,
			LogoUrl:   *s.GetLogoUrl(&item.ShortName),
		}
	})

	return result, nil
}

// Container of BankService functions.
type bankService struct {
	db             *sql.DB
	bankRepository repository.BankRepository
}
